package ac.github.oa.internal.core.item.generator

import ac.github.oa.OriginAttribute
import ac.github.oa.api.common.script.InlineScriptContext
import ac.github.oa.internal.core.item.Item
import ac.github.oa.internal.core.item.Translator
import ac.github.oa.internal.core.item.random.RandomFactor
import ac.github.oa.util.random
import ac.github.oa.util.rebuild
import org.bukkit.Color
import org.bukkit.Material
import org.bukkit.entity.LivingEntity
import org.bukkit.inventory.ItemFlag
import org.bukkit.inventory.ItemStack
import taboolib.common.LifeCycle
import taboolib.common.platform.Awake
import taboolib.common5.Coerce
import taboolib.library.xseries.XEnchantment
import taboolib.module.nms.ItemTag
import taboolib.module.nms.ItemTagData
import taboolib.module.nms.ItemTagList
import taboolib.module.nms.getItemTag
import taboolib.platform.BukkitPlugin
import taboolib.platform.util.ItemBuilder
import java.util.*
import java.util.logging.Level

@Awake(LifeCycle.LOAD)
open class DefaultGenerator : ItemGenerator {

    override val name: String
        get() = ""

    override fun build(entity: LivingEntity?, item: Item, map: MutableMap<String, String>): ItemStack {

        val config = item.config

        val factor = RandomFactor(InlineScriptContext(entity).also { it.data += map })

        factor.create(config.getStringList("create-pre"))

        val id = factor.create(item.id)

        val material = try {
            Material.valueOf(id.toString().uppercase())
        } catch (_: Exception) {
            BukkitPlugin.getInstance().logger.log(Level.WARNING, "无效的id $id,追踪节点 ${config.name}.")
            Material.STONE
        }
        val builder = ItemBuilder(material)

        builder.name = factor.create(item.name).toString()
        builder.damage = factor.create(item.damage).toInt()
        builder.lore += factor.create(item.lore).toList()
        builder.isUnbreakable = item.isUnBreakable


        factor.create(item.enchantments).toList().forEach {
            val split = it.split(":")
            val key = XEnchantment.matchXEnchantment(split[0]).get().enchant!!
            val level = if (split.size == 2) split[1].toInt() else key.startLevel
            builder.enchants[key] = (builder.enchants[key] ?: 0) + level
        }

        builder.flags += factor.create(item.itemFlags).toList()
            .map { ItemFlag.valueOf(it.uppercase()) }


        val attackSpeed = factor.createOrNull(item.attackSpeed)?.toString()

        builder.skullOwner = factor.createOrNull(item.skillOwner)?.toString()

        builder.skullTexture = factor.createOrNull(item.skillTexture)?.toSkullTexture()
        
        builder.color = factor.createOrNull(item.color)?.toColor()

        builder.colored()

        builder.finishing = {
            val itemTag = it.getItemTag()
            val json = OriginAttribute.json.toJson(factor.context.data)
            itemTag["oa-session"] = ItemTagData(json)

            config.getConfigurationSection("nbt")?.getKeys(false)?.forEach {
                val path = "nbt.$it"
                if (config.isList(path)) {
                    itemTag[it] = Translator.toNBTBase(factor.create(config.getStringList(path)).toList())
                } else if (config.isString(it)) {
                    itemTag[it] = Translator.toNBTBase(factor.create(config.getString(path)!!).toString())
                } else {
                    itemTag[it] = Translator.toNBTBase(config[path])
                }
            }

            if (item.isClearDefault) {
                itemTag["AttributeModifiers"] = ItemTagData(ItemTagList())
            }
            if (attackSpeed != null) {

                val attributeModifiers = itemTag["AttributeModifiers"]?.asList() ?: ItemTagList()
                attributeModifiers.add(
                    createAttributeModifier("generic.attackSpeed", "AttackSpeed", Coerce.toDouble(attackSpeed), 0)
                )
                itemTag["AttributeModifiers"] = attributeModifiers
            }
            itemTag.saveTo(it)
        }

        return builder.build()
    }

    fun createAttributeModifier(attributeName: String, name: String, amount: Double, operation: Int): ItemTag {
        return ItemTag().also {
            it["AttributeName"] = ItemTagData(attributeName)
            it["Name"] = ItemTagData(name)
            it["Amount"] = ItemTagData(amount)
            it["Operation"] = ItemTagData(operation)
            it["UUIDLeast"] = ItemTagData(20000)
            it["UUIDMost"] = ItemTagData(1000)
        }
    }


}